//--------------------------------------------------------------------------------------
// Defines
//--------------------------------------------------------------------------------------
#define ESHARPENING //enable sharpening
#define ESHARPENINGCOLOR //if defined, color sharpen, otherwise sharp by gray
#define ENOISE //enable noise in dark areas

//--------------------------------------------------------------------------------------
// Vectors, floats and etc.
//--------------------------------------------------------------------------------------

float ShiftSamplingRange=0.1;
float SamplingRange=0.5; //sharpening or blurring range
float SharpeningAmount=1.5;
float ScanLineAmount=0;
float ScanLineRepeat=0; //0.5, 0.3333, 0.25, 0.125, so on
float NoiseAmount=0.0;


//keyboard controled variables
float	tempF1;
float	tempF2;
float	tempF3;
float	tempF4;
float	tempF5;
float	tempF6;
float	tempF7;
float	tempF8;
float	tempF9;
float	tempF0;


//global variables, already set before executing this code
float	ScreenSize;	//width of the display resolution (2048 f.e.)
float	ScreenScaleY;	//screen proportions (2.555 for 2560/1600)
float	ScreenBrightnessAdaptation;//(-10..10) for bloom it controls how much to dark in the night or when scene is dark (user defined constant factor)
float	bloomPower;//(2..10) actually used for bloom, but may be useful here (user defined constant factor)
float	useBloom;//(1 or 1) if bloom enabled by user


//--------------------------------------------------------------------------------------
// Textures
//--------------------------------------------------------------------------------------

texture2D texColor;
texture2D texNoise;

//--------------------------------------------------------------------------------------
// Functions
//--------------------------------------------------------------------------------------

float Luminance( float3 c )
{
	return dot( c, float3(0.22, 0.707, 0.071) );
}

//--------------------------------------------------------------------------------------
// Sampler Inputs
//--------------------------------------------------------------------------------------
sampler2D SamplerColor = sampler_state
{
Texture   = <texColor>;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = NONE;//NONE;
AddressU  = Clamp;
AddressV  = Clamp;
SRGBTexture=FALSE;
MaxMipLevel=0;
MipMapLodBias=0;
};

sampler2D SamplerNoise = sampler_state
{
Texture   = <texNoise>;
MinFilter = POINT;
MagFilter = POINT;
MipFilter = NONE;//NONE;
AddressU  = Wrap;
AddressV  = Wrap;
SRGBTexture=FALSE;
MaxMipLevel=0;
MipMapLodBias=0;
};

struct VS_OUTPUT_POST {
float4 vpos  : POSITION;
float2 txcoord : TEXCOORD0;
};

struct VS_INPUT_POST {
float3 pos  : POSITION;
float2 txcoord : TEXCOORD0;
};

//--------------------------------------------------------------------------------------
// Functions
//--------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------
// Vertex Shader Input
//--------------------------------------------------------------------------------------

VS_OUTPUT_POST VS_PostProcess(VS_INPUT_POST IN)
{
VS_OUTPUT_POST OUT;

float4 pos=float4(IN.pos.x,IN.pos.y,IN.pos.z,1.0);

OUT.vpos=pos;
OUT.txcoord.xy=IN.txcoord.xy;

return OUT;
}



//--------------------------------------------------------------------------------------
// Pixel Shader Effects
//--------------------------------------------------------------------------------------
float4 PS_PostProcess(VS_OUTPUT_POST In) : COLOR
{
/*
float	tempF1=1.0;
float	tempF2=1.0;
float	tempF3=1.0;
float	tempF4=1.0;
float	tempF5=1.3;
float	tempF6=4.35;
float	tempF7=1.12;
float	tempF8=1.2;
float	tempF9=3.17;
float	tempF0=1.4;
*/
//START TO MAKE YOUR CHANGES FROM HERE
	float4 res;
	float4 uvsrc=0;
	uvsrc.xy=In.txcoord;

	res=0.0;
	float4 coord=0.0;
	coord.xy=In.txcoord.xy;
	float4 origcolor=tex2D(SamplerColor, coord.xy);
	float origgray=max(origcolor.r, max(origcolor.g, origcolor.b));


float2 dir=0.0;

	float4 color;




dir.xy=2.0*pow(origgray,0.3)/ScreenSize;//tempF9*
//dir.xy=2.0*pow(origgray,0.5) * float2(tempF9, tempF9)/ScreenSize;

coord.xy=In.txcoord+dir.xy*1.5;
color.r=tex2D(SamplerColor, coord.xy).r;

coord.xy=In.txcoord+dir.xy*0.5;
color.g=tex2D(SamplerColor, coord.xy).g;

coord.xy=In.txcoord+dir.xy*0.5;
color.b=tex2D(SamplerColor, coord.xy).b;

res.xyz=color.xyz;


/*
dir.xy=tempF9*1.0*pow(origgray,0.5)/ScreenSize;
//dir.xy=2.0*pow(origgray,0.5) * float2(tempF9, tempF9)/ScreenSize;

coord.xy=In.txcoord-dir.xy*1.0;
color.r=tex2D(SamplerColor, coord.xy).r;

coord.xy=In.txcoord;//+dir.xy*0.5;
color.g=tex2D(SamplerColor, coord.xy).g;

coord.xy=In.txcoord+dir.xy*1.0;
color.b=tex2D(SamplerColor, coord.xy).b;

res.xyz=max(color.xyz, origcolor.xyz);

*/

	res.a=1.0;
	return  res;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//--------------------Fast Approximate Anti-Aliasing --------------------------
//         FXAA v2 CONSOLE by TIMOTHY LOTTES @ NVIDIA   
//          Ported to ENBSeries by MysTer92 (Svyatoslav Gampel)
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
float4 PS_PostProcess2(VS_OUTPUT_POST i) : COLOR
{
	#define FXAA_SUBPIX_SHIFT (1.0/64.0)
	#define FXAA_REDUCE_MIN   (1.0/64.0)
	#define FXAA_REDUCE_MUL   (1.0/64.0)
	#define FXAA_SPAN_MAX     64.0
	
	half2 rcpFrame = half2(1/ScreenSize, 1/(ScreenSize/ScreenScaleY));
	
	half4 posPos;
	posPos.xy = i.txcoord.xy;
	posPos.zw = posPos.xy - (rcpFrame.xy * (0.5 + FXAA_SUBPIX_SHIFT));
	
	half3 rgbNW = tex2D(SamplerColor, posPos.zw ).xyz;
	half3 rgbNE = tex2D(SamplerColor, posPos.zw + half2(rcpFrame.x, 0.0) ).xyz;
	half3 rgbSW = tex2D(SamplerColor, posPos.zw + half2(0.0, rcpFrame.y) ).xyz;
	half3 rgbSE = tex2D(SamplerColor, posPos.zw +rcpFrame.xy ).xyz;
	half3 rgbM  = tex2D(SamplerColor, posPos.xy).xyz;
				    
	half3 luma = half3(0.299, 0.587, 0.114);
	half lumaNW = dot(rgbNW, luma);
	half lumaNE = dot(rgbNE, luma);
	half lumaSW = dot(rgbSW, luma);
	half lumaSE = dot(rgbSE, luma);
	half lumaM  = dot(rgbM,  luma);
				    
	half lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
	half lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
				    
	half2 dir; 
				    
	half lumaNWNE = lumaNW + lumaNE;
	half lumaSWSE = lumaSW + lumaSE;
				    
	dir.x = -((lumaNWNE) - (lumaSWSE));
	dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));
				    
	half dirReduce = max( (lumaSWSE + lumaNWNE) * (0.25 * FXAA_REDUCE_MUL),
									FXAA_REDUCE_MIN);
	half rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);
	dir = min(half2( FXAA_SPAN_MAX,  FXAA_SPAN_MAX), 
				max(half2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), 
				dir * rcpDirMin)) * rcpFrame.xy;
				          
	half3 rgbA = (1.0/2.0) * (
		tex2D(SamplerColor, posPos.xy + dir * (1.0/3.0 - 0.5) ).xyz +
		tex2D(SamplerColor, posPos.xy + dir * (2.0/3.0 - 0.5) ).xyz);
	half3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (
		tex2D(SamplerColor, posPos.xy + dir * (0.0/3.0 - 0.5) ).xyz +
		tex2D(SamplerColor, posPos.xy + dir * (3.0/3.0 - 0.5) ).xyz);
	half lumaB = dot(rgbB, luma);
				    
	if((lumaB < lumaMin) || (lumaB > lumaMax))
		return half4(rgbA, 1.0);
				    
	return float4(rgbB, 1.0);
}

float4 PS_PostProcess3(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
float4 res;
float4 coord=0.0;

coord.xy=IN.txcoord.xy;
float4 origcolor;

coord.w=0.0;


origcolor=tex2Dlod(SamplerColor, coord);

// coord.x=IN.txcoord.x-(1.5/ScreenSize);
// float4 lshift=tex2Dlod(SamplerColor, coord);
// coord.x=IN.txcoord.x+(1.5/ScreenSize);
// float4 rshift=tex2Dlod(SamplerColor, coord);


float2 offset[8]=
{
float2(1.0, 1.0),
float2(-1.0, -1.0),
float2(-1.0, 1.0),
float2(1.0, -1.0),

float2(1.41, 0.0),
float2(-1.41, 0.0),
float2(0.0, 1.41),
float2(0.0, -1.41)
};
int i=0;

float4 tcol=origcolor;
float invscreensize=1.0/ScreenSize;
//for (i=0; i<8; i++) //higher quality
for (i=0; i<8; i++)
{
float2 tdir=offset[i].xy;
coord.xy=IN.txcoord.xy+tdir.xy*invscreensize*SamplingRange;//*1.0;
float4 ct=tex2Dlod(SamplerColor, coord);

tcol+=ct;
}
tcol*=0.111; // 8.0/(4+1)
//tcol*=0.111; // 8.0/(8+1)  //higher quality


/*
//not interesting
#ifdef EBLURRING
//blur
res=tcol;
#endif
*/

//sharp
#ifdef ESHARPENING

#ifdef ESHARPENINGCOLOR
//color
res=origcolor*(1.0+((origcolor-tcol)*SharpeningAmount));
#else
//non color
float difffact=dot((origcolor.xyz-tcol.xyz), 0.333);
res=origcolor*(1.0+difffact*SharpeningAmount);
#endif

//less sharpening for bright pixels
float rgray=origcolor.z; //blue fit well
//float rgray=max(origcolor.x, max(origcolor.y, origcolor.z));
rgray=pow(rgray, 3.0);
res=lerp(res, origcolor, saturate(rgray));

#endif




//grain noise
#ifdef ENOISE
float origgray=max(res.x, res.y);//dot(res.xyz, 0.333);
origgray=max(origgray, res.z);
coord.xy=IN.txcoord.xy*16.0 + origgray;
float4 cnoi=tex2Dlod(SamplerNoise, coord);
res=lerp(res, (cnoi.x+1)*res, NoiseAmount*saturate(1.0-origgray*1.0));
#endif


res.w=1.0;
return res;
}

float4 PS_Process4(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
float4 res;
float4 coord=0.0;

coord.xy=IN.txcoord.xy;
float4 origcolor;

coord.w=0.0;


origcolor=tex2Dlod(SamplerColor, coord);

// coord.x=IN.txcoord.x-(1.5/ScreenSize);
// float4 lshift=tex2Dlod(SamplerColor, coord);
// coord.x=IN.txcoord.x+(1.5/ScreenSize);
// float4 rshift=tex2Dlod(SamplerColor, coord);


float2 offset[8]=
{
 float2(1.0, 1.0),
 float2(-1.0, -1.0),
 float2(-1.0, 1.0),
 float2(1.0, -1.0),

 float2(1.41, 0.0),
 float2(-1.41, 0.0),
 float2(0.0, 1.41),
 float2(0.0, -1.41)
};
int i=0;

float4 tcol=origcolor;
float2 invscreensize=1.0/ScreenSize;
invscreensize.y=invscreensize.y/ScreenScaleY;
//for (i=0; i<8; i++) //higher quality
/*	for (i=0; i<4; i++)
{
 float2 tdir=offset[i].xy;
 coord.xy=IN.txcoord.xy+tdir.xy*invscreensize*SamplingRange;//*1.0;
 float4 ct=tex2Dlod(SamplerColor, coord);

 tcol+=ct;
}
tcol*=0.2; // 1.0/(4+1)
//tcol*=0.111; // 1.0/(8+1)  //higher quality
*/

coord.xy=IN.txcoord.xy;
origcolor=tex2Dlod(SamplerColor, coord);
res.y=origcolor.y;

coord.xy=IN.txcoord.xy;
coord.y-=invscreensize*ShiftSamplingRange;
origcolor=tex2Dlod(SamplerColor, coord);
res.x=origcolor.x;

coord.xy=IN.txcoord.xy;
coord.y+=invscreensize*ShiftSamplingRange;
origcolor=tex2Dlod(SamplerColor, coord);
res.z=origcolor.z;


res.w=1.0;
return res;
}


//--------------------------------------------------------------------------------------
// Compiler
//--------------------------------------------------------------------------------------

technique PostProcess
{
    pass P0
    {
	VertexShader = compile vs_3_0 VS_PostProcess();
	PixelShader  = compile ps_3_0 PS_PostProcess();

	FogEnable=FALSE;
	ALPHATESTENABLE=FALSE;
	SEPARATEALPHABLENDENABLE=FALSE;
	AlphaBlendEnable=FALSE;
	FogEnable=FALSE;
	SRGBWRITEENABLE=FALSE;
	}
}

technique PostProcess2
{
   pass P0
   {
VertexShader = compile vs_3_0 VS_PostProcess();
PixelShader  = compile ps_3_0 PS_PostProcess2();

FogEnable=FALSE;
ALPHATESTENABLE=FALSE;
SEPARATEALPHABLENDENABLE=FALSE;
AlphaBlendEnable=FALSE;
FogEnable=FALSE;
SRGBWRITEENABLE=FALSE;
}
}
technique PostProcess2
{
   pass P0
   {
VertexShader = compile vs_3_0 VS_PostProcess();
PixelShader  = compile ps_3_0 PS_PostProcess2();

FogEnable=FALSE;
ALPHATESTENABLE=FALSE;
SEPARATEALPHABLENDENABLE=FALSE;
AlphaBlendEnable=FALSE;
FogEnable=FALSE;
SRGBWRITEENABLE=FALSE;
}
}
technique PostProcess3
{
  pass P0
  {

VertexShader = compile vs_3_0 VS_PostProcess();
PixelShader  = compile ps_3_0 PS_PostProcess3();

DitherEnable=FALSE;
ZEnable=FALSE;
CullMode=NONE;
ALPHATESTENABLE=FALSE;
SEPARATEALPHABLENDENABLE=FALSE;
AlphaBlendEnable=FALSE;
StencilEnable=FALSE;
FogEnable=FALSE;
SRGBWRITEENABLE=FALSE;
}
}
technique PostProcess4
{
pass P0
{

 VertexShader = compile vs_3_0 VS_PostProcess();
 PixelShader  = compile ps_3_0 PS_Process4();

 DitherEnable=FALSE;
 ZEnable=FALSE;
 CullMode=NONE;
 ALPHATESTENABLE=FALSE;
 SEPARATEALPHABLENDENABLE=FALSE;
 AlphaBlendEnable=FALSE;
 StencilEnable=FALSE;
 FogEnable=FALSE;
 SRGBWRITEENABLE=FALSE;
}
}






